package com.parsechina.hpush.broker.utils;

import com.parsechina.hpush.broker.config.MqttConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author linfeng
 * @since 2016/11/22
 */
public final class StringUtils implements Serializable {


    private static final long serialVersionUID = -4922583106028152147L;

    private static final Logger LOG = LoggerFactory.getLogger(StringUtils.class);

    private StringUtils() {
    }

    /**
     * 转换
     *
     * @param source source
     * @return String
     */
    public static String convertAscii(String source) {
        StringBuilder asc = new StringBuilder();
        for (int i = 0; i < source.length(); i++) {
            int asd = source.charAt(i);
            asc.append(asd);
        }
        return asc.toString();
    }

    public static boolean isBlank(final String src) {
        return src == null || src.trim().isEmpty();
    }

    public static boolean isNotBlank(final String src) {
        return !isBlank(src);
    }

    /**
     * not empty.
     *
     * @param src     src
     * @param message 消息
     */
    public static void nonEmpty(String src, String message) {
        if (empty(src)) {
            throw new IllegalArgumentException(message);
        }
    }

    public static boolean empty(String src) {
        return src == null || src.trim().isEmpty();
    }

    /**
     * ..
     * 数组以分隔符转换成字符串
     *
     * @param strings 字符串数组
     * @param sep     分隔符
     * @return 字符串
     */
    public static String join(String[] strings, char sep) {
        StringBuilder builder = new StringBuilder();
        for (String str : strings) {
            builder.append(str);
            builder.append(sep);
        }
        builder.deleteCharAt(builder.length() - 1);

        return builder.toString();
    }

    /**
     * ..
     * 替换空格
     *
     * @param resource 原始字符�?
     * @param ch       待替换的字符或字符串
     * @return 替换后的字符
     */
    public static String replaceAs(final String resource, final String ch) {

        StringBuilder builder = new StringBuilder();
        int position = 0;
        while (position < resource.length()) {
            char currentChar = resource.charAt(position);
            position++;
            if (Character.isWhitespace(currentChar)) {
                builder.append(ch);
            } else {
                builder.append(currentChar);
            }
        }
        return builder.toString();

    }

    /**
     * ..
     * 删除空格
     *
     * @param resource 原始字符
     * @return 整理后的字符
     */
    public static String replaceBlank(final String resource) {

        StringBuilder builder = new StringBuilder();
        int position = 0;
        while (position < resource.length()) {
            char currentChar = resource.charAt(position);
            position++;
            if (!Character.isWhitespace(currentChar)) {
                builder.append(currentChar);
            }
        }
        return builder.toString();

    }

    /**
     * ..
     * 替换掉HTML标签方法
     *
     * @param html html字符串
     * @return 替换后的HTML字符串
     */
    public static String replaceHtml(final String html) {
        if (isBlank(html)) {
            return "";
        }
        String regEx = "<.+?>";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(html);
        return m.replaceAll("");
    }

    /**
     * ..
     * 缩略字符串（不区分中英文字符)
     *
     * @param str    目标字符�
     * @param length 截取长度
     * @return 字符串
     */
    public static String abbr(String str, int length) {
        if (str == null) {
            return "";
        }
        try {
            StringBuilder sb = new StringBuilder();
            int currentLength = 0;
            for (char c : str.toCharArray()) {
                currentLength += String.valueOf(c).getBytes("GBK").length;
                if (currentLength <= length - 3) {
                    sb.append(c);
                } else {
                    sb.append("...");
                    break;
                }
            }
            return sb.toString();
        } catch (UnsupportedEncodingException ignored) {
            LOG.error(ignored.getMessage());
        }
        return "";
    }

    /**
     * ..
     * 转换为Double类型
     */
    public static Double toDouble(Object val) {
        if (val == null) {
            return 0.0D;
        }
        try {
            return Double.valueOf(val.toString().trim());
        } catch (Exception e) {
            return 0.0D;
        }
    }

    /**
     * ..
     * 转换为Float类型
     */
    public static Float toFloat(Object val) {
        return toDouble(val).floatValue();
    }

    /**
     * ..
     * 转换为Long类型
     */
    public static Long toLong(Object val) {
        return toDouble(val).longValue();
    }

    /**
     * ..
     * 转换为Integer类型
     */
    public static Integer toInteger(Object val) {
        return toLong(val).intValue();
    }

    public static String[] tokenizeToStringArray(String str,
                                                 String delimiters) {
        return tokenizeToStringArray(str, delimiters, true, true);
    }

    public static String[] tokenizeToStringArray(String str, String delimiters,
                                                 boolean trimTokens, boolean ignoreEmptyTokens) {

        if (str == null) {
            return null;
        }
        StringTokenizer st = new StringTokenizer(str, delimiters);
        List<String> tokens = new ArrayList<String>();
        while (st.hasMoreTokens()) {
            String token = st.nextToken();
            if (trimTokens) {
                token = token.trim();
            }
            if (!ignoreEmptyTokens || !token.isEmpty()) {
                tokens.add(token);
            }
        }
        return toStringArray(tokens);
    }

    public static String[] toStringArray(Collection<String> collection) {
        if (collection == null) {
            return null;
        }
        return collection.toArray(new String[collection.size()]);
    }

    public static boolean hasLength(CharSequence str) {
        return str != null && str.length() > 0;
    }

    public static boolean hasLength(String str) {
        return hasLength((CharSequence) str);
    }

    public static boolean hasText(CharSequence str) {
        if (!hasLength(str)) {
            return false;
        }
        int strLen = str.length();
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    public static boolean hasText(String str) {
        return hasText((CharSequence) str);
    }

    public static boolean containsWhitespace(CharSequence str) {
        if (!hasLength(str)) {
            return false;
        }
        int strLen = str.length();
        for (int i = 0; i < strLen; i++) {
            if (Character.isWhitespace(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    public static boolean containsWhitespace(String str) {
        return containsWhitespace((CharSequence) str);
    }

    public static String trimWhitespace(String str) {
        if (!hasLength(str)) {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
            sb.deleteCharAt(0);
        }
        while (sb.length() > 0
                && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    public static String trimAllWhitespace(String str) {
        if (!hasLength(str)) {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        int index = 0;
        while (sb.length() > index) {
            if (Character.isWhitespace(sb.charAt(index))) {
                sb.deleteCharAt(index);
            } else {
                index++;
            }
        }
        return sb.toString();
    }

    public static String trimLeadingWhitespace(String str) {
        if (!hasLength(str)) {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
            sb.deleteCharAt(0);
        }
        return sb.toString();
    }

    public static String trimTrailingWhitespace(String str) {
        if (!hasLength(str)) {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() > 0
                && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    public static String trimLeadingCharacter(String str,
                                              char leadingCharacter) {
        if (!hasLength(str)) {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() > 0 && sb.charAt(0) == leadingCharacter) {
            sb.deleteCharAt(0);
        }
        return sb.toString();
    }

    public static String trimTrailingCharacter(String str,
                                               char trailingCharacter) {
        if (!hasLength(str)) {
            return str;
        }
        StringBuilder sb = new StringBuilder(str);
        while (sb.length() > 0
                && sb.charAt(sb.length() - 1) == trailingCharacter) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }


    public static String replace(String inString, String oldPattern,
                                 String newPattern) {
        if (!hasLength(inString) || !hasLength(oldPattern)
                || newPattern == null) {
            return inString;
        }
        StringBuilder sb = new StringBuilder();
        int pos = 0; // our position in the old string
        int index = inString.indexOf(oldPattern);
        // the index of an occurrence we've found, or -1
        int patLen = oldPattern.length();
        while (index >= 0) {
            sb.append(inString.substring(pos, index));
            sb.append(newPattern);
            pos = index + patLen;
            index = inString.indexOf(oldPattern, pos);
        }
        sb.append(inString.substring(pos));
        // remember to append any characters to the right of a match
        return sb.toString();
    }

    public static String delete(String inString, String pattern) {
        return replace(inString, pattern, "");
    }

    public static String deleteAny(String inString, String charsToDelete) {
        if (!hasLength(inString) || !hasLength(charsToDelete)) {
            return inString;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < inString.length(); i++) {
            char c = inString.charAt(i);
            if (charsToDelete.indexOf(c) == -1) {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static String quote(String str) {
        return str != null ? "'" + str + "'" : null;
    }

    public static String unqualify(String qualifiedName) {
        return unqualify(qualifiedName, '.');
    }

    public static String unqualify(String qualifiedName, char separator) {
        return qualifiedName
                .substring(qualifiedName.lastIndexOf(separator) + 1);
    }

    /**
     * 首字母大�?.
     *
     * @param str str
     * @return String
     */
    public static String capitalize(String str) {
        return changeFirstCharacterCase(str, true);
    }

    /**
     * 首字母小�?.
     *
     * @param str str
     * @return String
     */
    public static String uncapitalize(String str) {
        return changeFirstCharacterCase(str, false);
    }

    private static String changeFirstCharacterCase(String str,
                                                   boolean capitalize) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        StringBuilder sb = new StringBuilder(str.length());
        if (capitalize) {
            sb.append(Character.toUpperCase(str.charAt(0)));
        } else {
            sb.append(Character.toLowerCase(str.charAt(0)));
        }
        sb.append(str.substring(1));
        return sb.toString();
    }

    /**
     * 判断给定的字符串的长度是否否和规定的长度.
     *
     * @param source s
     * @param len    l
     * @return true:符合
     */
    public static boolean isEqualLen(String source, int len) {
        if (source != null) {
            if (source.length() == len) {
                return true;
            }
        } else if (len == 0) {
            return true;
        }
        return false;
    }

    /**
     * 判断给定的字符串的长度是否小于等于规定的长度
     *
     * @param source s
     * @param len    l
     * @return true:符合
     */
    public static boolean isLessEqualLen(String source, int len) {
        if (source == null || "".equals(source)) {
            return len >= 0;
        }
        return source.length() <= len;
    }

    /**
     * 替换原字符为新的字符
     *
     * @param source 源字符串
     * @param s      要替换的字符
     * @param e      新字符
     * @return String
     */
    public static String replaceAll(String source, String s, String e) {
        if (source == null) {
            return source;
        }
        return source.replaceAll(s, e);
    }

    /**
     * 对象序列化为字符串
     */
    @SuppressWarnings("NonSerializableObjectPassedToObjectStream")
    public static String serialize(Object obj) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(obj);
        String serStr = byteArrayOutputStream.toString("ISO-8859-1");//必须是ISO-8859-1
        serStr = URLEncoder.encode(serStr, "UTF-8");//编码后字符串不是乱码（不编也不影响功能）

        objectOutputStream.close();
        byteArrayOutputStream.close();
        return serStr;
    }

    /**
     * 字符串 反序列化为 对象
     */
    public static Object unSerialize(String serStr) throws Exception {
        String redStr = URLDecoder.decode(serStr, "UTF-8");
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(redStr.getBytes("ISO-8859-1"));
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Object obj = objectInputStream.readObject();

        objectInputStream.close();
        byteArrayInputStream.close();
        return obj;
    }

    /**
     * 把字节转换成字符串
     *
     * @param s 字节
     * @return String
     */
    public static String encodeUTF8(byte... s) {
        return new String(s, MqttConstants.UTF8);
    }

    /**
     * 在请求路径上添加参数
     *
     * @return String
     */
    public static String pathAppendParameter(String path, String param) {
        String path1 = path;
        if (path1 == null || "".equals(param)) {
            return "";
        }
        if (param == null || "".equals(param)) {
            return path1;
        }

        if (path1.contains("?")) {
            path1 = path1 + "&" + param;
            return path1;
        }
        return path1 + "?" + param;
    }

}
